
	#include <stdio.h>
	#include <string.h>
	#include "../src/nary.c"
        #include "bst_operations.c"
	#include "../src/hashtable.c"
  	#include "../include/vfs_errorcodes.h"
	//All variables declaration
	fd fd1, fd2;
	main_header main_header1;
	int fd_count=0;
	int mountState=0;
/*
#define ERR_VFS_CREATE_00 "createvfs_FAILURE VFS_INSUFFICIENT_ARGUMENTS" 
#define ERR_VFS_CREATE_01 "createvfs_FAILURE DATA_FILE_ALREADY_EXISTS"
#define ERR_VFS_CREATE_02 "createvfs_FAILURE CANNOT_CREATE_DATAFILE"

 // The slash (/) character is not allowed
#define ERR_VFS_CREATE_03 "createvfs_FAILURE INVALID_CHARACTER_IN_NAME"
// Valid range for size is 1 to 1024 (inclusive)
#define ERR_VFS_CREATE_04 "createvfs_FAILURE INVALID_SIZE"
//New   (If label name exceeds 30 characters)
#define ERR_VFS_CREATE_05 "createvfs_FAILURE VFS_LABEL_TOO_LARGE"  


*/
	//Create VFS function
	int create_vfs(char *label, int size)
	{
	
	/*
		FileSystem Information of VFS is Like:

			Total size = Metaheader + All Filedescriptors + FreeLIst + Blocks
			totalNO of Blocks = No of File_discriptors(almost)
			Total size = sizeof(metaheader) + noBlockssizeof(fileDescriptor) + noBlockssizeof(int) //this is for freelist(int)  + 				noBlockssizeof(block)
	*/

	int i, numofBlocks;
        int *p;
        FILE *fp;
	if (strlen(label) == 0) {
		printf("%s\n",ERR_VFS_CREATE_00);//ERR_VFS_CREATE_00
		return 0;
  	}
	
	for(i=0;i<strlen(label);i++){
		//printf("%c\n",label[i]);
		if(label[i]=='/'){
			printf("%s\n",ERR_VFS_CREATE_03);
			return 0;
		}
	}
        
	
	if(strlen(label)>30){
		printf("%s\n",ERR_VFS_CREATE_05);
		return 0;
	}
	if(size<=0 || size >1024){
		printf("%s\n",ERR_VFS_CREATE_04);
		return 0;
	}
	
	 if((fp = fopen(label,"wb+"))==NULL) 
        {
                printf("%s\n",ERR_VFS_CREATE_02);
                return 0;
        }
	 
	 fseek(fp,0, SEEK_SET); 
        //Converting size in KBytes to Bytes
        if (size<=100) size+=200;
        size = size * 1024;
        
  
        //Writing main_header into VFS


        numofBlocks = ( size - sizeof(main_header) ) / ( sizeof(fd) + sizeof(int) + sizeof(block) );
                

        strcpy(main_header1.file_system_label, label);
        main_header1.max_file_descriptor = numofBlocks;
        main_header1.used_file_descriptor = 0;
        main_header1.used_blocks= 0;
        main_header1.Total_Blocks = numofBlocks;
        fwrite( &main_header1, sizeof(main_header),1,fp);

        
	//creating and writing File Descriptors       
        fd f;
        for(i=0; i<main_header1.max_file_descriptor; i++)
                fwrite(&f, sizeof(fd), 1, fp);
        //printf("Total Size for File Descriptors: %d\n", sizeof(fd)*main_header1.max_file_descriptor);


        //Creating FreeList...
	
        freelist = (int*) malloc(sizeof(int)*numofBlocks);
	for(i=0; i<numofBlocks; i++){ //initialize freelist array to 0
	      *(freelist+i) = 0; 
	}
        for(i=0; i<main_header1.Total_Blocks; i++){
              fwrite(freelist+i, sizeof(int), 1, fp);        //writing freelist array to file one int at a time 
         }

        //Creating and writing Blocks(Data Blocks)
        //printf("Number of blocks are: %d\n", main_header1.Total_Blocks);
        //printf("Total size data blocks: %d\n", main_header1.Total_Blocks*sizeof(block));
        block b;
        for(i=0; i<main_header1.Total_Blocks; i++)
                fwrite(&b, sizeof(block), 1, fp);

        fclose(fp);
        printf("createvfs_SUCCESS\n");
        return 0; //return VFS_01_SUCCESS;
 }
/*

#define ERR_VFS_MOUNT_00 "mountvfs_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_MOUNT_01 "mountvfs_FAILURE DATA_FILE_NOT_FOUND"
#define ERR_VFS_MOUNT_02 "mountvfs_FAILURE CANNOT_READ_FROM_FILE" 
//New
#define ERR_VFS_MOUNT_03 "mountvfs_FAILURE VFS_ALREADY_MOUNTED"

*/

int mount_vfs(char *fileSystemLabel)
 {
	if(mountState==1){
		printf("%s\n",ERR_VFS_MOUNT_03);
		return 0; 
	}
	if (strlen(fileSystemLabel) == 0) {
		printf("%s\n",ERR_VFS_MOUNT_00);//ERR_VFS_CREATE_00
		return 0;
  	}
  	FILE *fp = fopen(fileSystemLabel, "rb+");
	if(fp==NULL){
		printf("%s\n",ERR_VFS_MOUNT_01);
		// return ERR_VFS_MOUNT_02
		return 0;
	}
	 
	int i;
	int k;
	int index = 0;
	int count=0;
	//printf("\n Mounting VFS %s \n",fileSystemLabel);
	fseek(fp, 0, SEEK_SET);
	
	fread(&main_header1, sizeof(main_header), 1, fp);
	
	// VFS start point...
	// put freelist array before fd array
	metaheader_startpoint= 0;
	fd_startpoint= metaheader_startpoint + sizeof(main_header);
	freelist_startpoint = fd_startpoint + ( sizeof(fd)*(main_header1.max_file_descriptor) );
	block_startpoint = freelist_startpoint + ( sizeof(int)*main_header1.Total_Blocks );

	//if(main_header1.used_file_descriptor==0)
	       //printf("Your VFS is Empty \n");
		
	
	if(main_header1.used_file_descriptor==0){//main_header1.used_file_descriptor==0){
	//Inserting / as the root
	//printf("1111111111111111111");
         strcpy(fd2.filename, "root");
         strcpy(fd2.path, "/");
         strcpy(fd2.filetype, "root");
         fd2.filesize = 0;
         fd2.blockno = -1;
	 initialize_root(&fd2);
	 initialize_bst_root(&fd2);
         //bst_root=insert_bstnode(bst_root, &fd2);
	 main_header1.used_file_descriptor++;
	 //display_bst(bst_root);
	file_descriptors[fd_count]=&fd2;
	//file_descriptors[fd_count]=&fd2;
	fd_count++;
         *freelist=1;
	}

	fseek(fp, fd_startpoint+sizeof(fd), SEEK_SET);
        //fseek(fp, fd_startpoint, SEEK_SET);
        // for(i=0;i<main_header1.used_file_descriptor;i++)
	  //        printf("%s\n",file_descriptors[i]->path);  

        for(i=0; i<main_header1.used_file_descriptor-1; i++){      //Testing whether writing works
         fread(&fd1, sizeof(fd), 1, fp);
         
         if(ferror(fp)){
         printf("%s\n",ERR_VFS_MOUNT_02);
         return 0;
         
         }
			
	 insert_nary(&fd1); 
	 bst_root = insert_bstnode(bst_root,&fd1);
	//display_bst(bst_root);
	 if(strcmp(fd1.filetype,"file")==0){
           index = hash_val(fd1.filename);
	   array[index] = insertnode(array[index],&fd1);
         }
        
        }
	//printf("\n Displaying BST.....\n");
	//display_bst(bst_root);
	//printf("\n Displaying NARY.....\n");
    	//display_nary(naryroot);
	
	mountState=1;
	
        fclose(fp);

	 printf("mountvfs_SUCCESS\n");
	return 1;
}

/*
int getinstruction(char *str, char *instr)
{
	char *i=str, *j=instr;
	while(*j!='\0' && *j==*i)
	{
	        i++;
	        j++;
	}
	if(*j=='\0') return 1;
	else return 0;
}
*/

/*



#define ERR_VFS_UNMOUNT_00 "unmountvfs_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
// Use when fopen fails
#define ERR_VFS_UNMOUNT_01 "unmountvfs_FAILURE DATA_FILE_NOT_FOUND"
// Use when fwrite fails
#define ERR_VFS_UNMOUNT_02 "unmountvfs_FAILURE CANNOT_WRITE_TO_FILE"
//New 
#define ERR_VFS_UNMOUNT_03 "unmountvfs_FAILURE VFS_NOT_MOUNTED"

*/

int unmount_vfs(char *file_system_label)
{
	if (strlen(file_system_label) == 0) {
		printf("%s\n",ERR_VFS_UNMOUNT_00);//
		return 0;
  	}
  	
  	if(mountState==0){
		printf("%s\n",ERR_VFS_UNMOUNT_03);
		return 0; 
	}
	
	FILE *fp1 = fopen(file_system_label, "rb");
	if(fp1==NULL){
		printf("%s\n",ERR_VFS_UNMOUNT_01);
		return 0;
		}
	fclose(fp1);


	
	 
	
        int i;
        
	FILE *fp = fopen(file_system_label, "rb+");
	if(!fp){
		printf("%s\n",ERR_VFS_UNMOUNT_02);
		return 0;
		}
	
	fseek(fp, metaheader_startpoint, SEEK_SET);
	
	fwrite(&main_header1, sizeof(main_header), 1, fp);
        fseek(fp, fd_startpoint, SEEK_SET);
	
	nary_write(naryroot,fp);
        fseek(fp, fd_startpoint, SEEK_SET);
        mountState=0;
 	fclose(fp);
	
        printf("unmountvfs_SUCCESS\n"); 
        //printf("\n No of used fd = %d\n", main_header1.used_file_descriptor);
	 //printf("\nfd count = %d\n", fd_count);
	return 0;
}


/*
#define ERR_VFS_MAKEDIR_00 "makedir_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
//changed to FILESYSTEM_FULL from UNABLE_TO_CREATE_NEWDIR
#define ERR_VFS_MAKEDIR_01 "makedir_FAILURE FILESYSTEM_FULL"
#define ERR_VFS_MAKEDIR_02 "makedir_FAILURE INVALID_CHARACTER_IN_DIRNAME"
#define ERR_VFS_MAKEDIR_03 "makedir_FAILURE DIRECTORY_ALREADY_EXISTS"
//New
#define ERR_VFS_MAKEDIR_05 "makedir_FAILURE VFS_NOT_MOUNTED"

*/
int make_dir(char destpath[], char dirname[]){
	
	if (strlen(destpath) == 0 || strlen(dirname) == 0) {
	printf("%s\n",ERR_VFS_MAKEDIR_00);//ERR_VFS_MAKEDIR_00
	return 0;
  	}
  	
  	if(mountState==0){
		printf("%s\n",ERR_VFS_MAKEDIR_05);//ERR_VFS_MAKEDIR_05
		return 0; 
   	}
  fd *filedes;
  char newdirpath[100];
  int index = 0;
  int i=0;
  fd *tmp;
  char destpath1[100];
  strcpy(destpath1,destpath);
  

   if(main_header1.max_file_descriptor == main_header1.used_file_descriptor){
		printf("%s\n",ERR_VFS_MAKEDIR_01);
		return 0;
	}

   for(i=0;i<strlen(dirname);i++)
   {
		if(dirname[i]=='/')
		{
			printf("%s\n",ERR_VFS_MAKEDIR_02);//ERR_VFS_MAKEDIR_02
			return 0;
		}
    } 
  if(strcmp(destpath, "/")!=0)
    strcat(destpath1, "/");
  //printf("Destination path: %s", destpath);
  strcat(destpath1, dirname);
  if(search_bstnode(bst_root,destpath1)==-1){
	printf("%s\n",ERR_VFS_MAKEDIR_03);
	return 0;//ERR_VFS_MAKEDIR_03
  }
  if(search_bstnode(bst_root,destpath)==-1){
   filedes = (fd *) malloc(sizeof(fd));
  strcpy(filedes->path,destpath1);
  strcpy(filedes->filename,dirname);
  strcpy(filedes->filetype,"dir");
  filedes->filesize = 0;
  filedes->blockno = -1;  

  naryroot = insert_nary(filedes);   
  bst_root = insert_bstnode(bst_root, filedes);
  main_header1.used_file_descriptor++;

  file_descriptors[fd_count]=filedes;
  fd_count++;
  }
  if(search_bstnode(bst_root,destpath1)==-100){
  	char *name;
	char name1[50]="/";
	char name2[70]="";
	name=strtok(destpath1,"/");
        while(name!=NULL)
	{
		
		//printf("\n to be inserted = %s",name);
		tmp =(fd*)malloc(sizeof(fd));
		strcat(name2,strcat(name1,name));
		strcpy(name1,"/");
		strcpy(tmp->path,name2);
		strcpy(tmp->filename,name);
		strcpy(tmp->filetype,"dir");
		tmp->filesize=0;
		tmp->blockno=-1;
                if(search_bstnode(bst_root, tmp->path)==-100){
                 main_header1.used_file_descriptor++;
		 file_descriptors[fd_count]=tmp;
		 fd_count++;
                }
		naryroot=insert_nary(tmp);
		bst_root = insert_bstnode(bst_root, tmp);
           	name=strtok(NULL,"/");
		
	}	
   
   }
  


//int block_num = search_bstnode (bst_root,destpath1);
//printf("%d",block_num);
  printf("makedir_SUCCESS\n");
  //return "MAKEDIR_SUCCESS";   //make_dir SUCCESS
   return 0;
}
/*
#define ERR_VFS_LISTDIR_00 "listdir_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_LISTDIR_01 "listdir_FAILURE CANNOT_FIND_SPECIFIED_PATH_OR_DIR"
#define ERR_VFS_LISTDIR_02 "listdir_FAILURE INVALID_FLAG"
#define ERR_VFS_LISTDIR_03 "listdir_FAILURE VFS_NOT_MOUNTED"
#define ERR_VFS_LISTDIR_04 "listdir_FAILURE CANNOT_CREATE_OUTPUTFILE"

*/


int list_dir(char *path,int flag,char *out_file) {

	if(mountState==0){
	printf("%s\n",ERR_VFS_LISTDIR_03);
	return 0;//return ERR_VFS_LISTDIR_03
    }
    if(flag!=0 && flag!=1){
	//printf("Flag not 0/1\n");
	printf("%s\n",ERR_VFS_LISTDIR_02);
	return 0;//return ERR_VFS_LISTDIR_02
    }
	if (strlen(path) == 0 || strlen(out_file) == 0 ) {
		printf("%s\n",ERR_VFS_LISTDIR_00);
		return 0;
	 }
	
    FILE *fp2;
    struct node* temp1;	
	//strcat(out_file,".txt");	   
    fp2 = fopen(out_file,"w+");
    
    if(fp2 == NULL) {
        printf("%s\n",ERR_VFS_LISTDIR_04);   
        return 0;//return ERR_VFS_LISTDIR_04
    }
   
    else{
	
		
	temp1 = searchn(naryroot,path);
	  
	//printf("the searched node %s\n",temp1->f->filename);	
	if(temp1 == NULL) {
		printf("%s\n",ERR_VFS_LISTDIR_01);
		return 0;//return ERR_VFS_LISTDIR_01	
	}
	else {
		temp1 = temp1->left;
		if(flag == 0)
			nonRecursive(temp1,fp2); 
		if(flag == 1)
		        Recursive(temp1,fp2);
	}
	//return 1;
	}
	fclose(fp2);
	printf("listdir_SUCCESS\n");
	return 1;
} 


/*
#define ERR_VFS_DELETEDIR_00 "deletedir_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_DELETEDIR_01 "deletedir_FAILURE CANNOT_FIND_SPECIFIED_DIR"
#define ERR_VFS_DELETEDIR_02 "deletedir_FAILURE DIRECTORY_IS_NOT_EMPTY"
//New
#define ERR_VFS_DELETEDIR_04 "deletedir_FAILURE VFS_NOT_MOUNTED"
*/
int delete_dir(char *fullpath){

  struct node *t1, *t;
  int i, index;
  
  //printf("In delete entry%s\n",fullpath);
  if(mountState==0){
	printf("%s\n",ERR_VFS_DELETEDIR_04);
	return 0;//return ERR_VFS_DELETEDIR_04;
  }
  if (strlen(fullpath) == 0) {
		printf("%s\n",ERR_VFS_MOVEFILE_00);
		return 0;
	 }
	 //printf("fullpath=%s",fullpath);
	 int blocknum = search_bstnode (bst_root,fullpath);
        	
        	if (blocknum != -1){
		//printf("%d\n",blocknum);
		//display_bst(bst_root);
        	printf("%s\n",ERR_VFS_DELETEDIR_01);
        	return 0;
        	}
	 
  t1 = naryroot;
  
  if(t1->left)
    t = t1->left;
  else{
    printf("%s\n",ERR_VFS_DELETEDIR_02);
    return 0;
  }

  int flag=1;
  while(flag)
	{

		if((strstr(fullpath,t->f->path))!=NULL && (strcmp(fullpath,t->f->path)!=0))
		{
 			 if(t->left){
 			    t1 = t;
    			    t = t->left;
			  }
  				
 			 else{
		          printf("%s\n",ERR_VFS_DELETEDIR_02); //invalid directory name
                          return 0;//return ERR_VFS_DELETEDIR_02;
			 }
		}

 		else if(strcmp(fullpath,t->f->path)==0)
		{
			flag=0;
			
  			if(t->left){   //Cannot delete directory which has contents.
                         printf("%s\n",ERR_VFS_DELETEDIR_02);//return ERR_VFS_DELETEDIR_02;
		         return 0;
  			}
                 
                        else{
                         if(t1->left == t){
                            t1->left = t->right;			     
			}
			 else   //t1->right = t
                            t1->right = t->right;			     
			}
			for(i = 0; i < fd_count; i++){
                           if(strcmp(file_descriptors[i]->path, fullpath)==0){
                              index = i;
                              break;
			    }
                       }
			main_header1.used_blocks--;
                      	main_header1.used_file_descriptor--;
			for(i=index; (i+1)<fd_count; i++){
                           file_descriptors[i] = file_descriptors[i+1];
                        }
                         fd_count--;
		}

		else
		{
			 if(t->right){
   			    t1 = t;
     			    t = t->right;
			  }

  			else{
			    printf("%s\n",ERR_VFS_DELETEDIR_02); 
                            return 0;//return ERR_VFS_DELETEDIR_02;
					
		         }
    		}
	}
printf("deletedir_SUCCESS\n");
}
//MOVE DIR
/*
#define ERR_VFS_MOVEDIR_00 "movedir_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_MOVEDIR_01 "movedir_FAILURE CANNOT_FIND_SPECIFIED_SOURCEDIR"
//(if specified dir is not there, it is not created in this case unlike in add dir)
#define ERR_VFS_MOVEDIR_02 "movedir_FAILURE CANNOT_FIND_SPECIFIED_DESTINATIONDIR"
//New
#define ERR_VFS_MOVEDIR_04 "movedir_FAILURE SOURCE_CANNOT_BE_FILE"
#define ERR_VFS_MOVEDIR_05 "movedir_FAILURE DESTINATION_ALREADY_HAVE_SOURCE_DIR"
//New
#define ERR_VFS_MOVEDIR_06 "movedir_FAILURE CANNOT_MOVE_PARENT_TO_CHILD_DIR"
//New
#define ERR_VFS_MOVEDIR_07 "movedir_FAILURE DESTINATION_CANNOT_BE_FILE"
//New
#define ERR_VFS_MOVEDIR_08 "movedir_FAILURE VFS_NOT_MOUNTED"
*/

void constructBST(struct node* root)
{   
    if(root!=NULL)
    {
        bst_root = insert_bstnode(bst_root,root->f);
        constructBST(root->left);   
        constructBST(root->right);
    }
           
}


int move_dir (char source_dir_path[],char dest_dir_path[])
{   
	if (strlen(source_dir_path) == 0 || strlen(dest_dir_path) == 0) {
            printf("%s\n",ERR_VFS_MOVEDIR_00);//ERR_VFS_MOVEDIR_00
        return;
     }
     if(mountState==0){
        printf("%s\n",ERR_VFS_MOVEDIR_08);//ERR_VFS_MOVEDIR_08
        return;
       }



 struct node *srcroot;
    int source_node,dest_node;
    char tmpPath[200]="";
    //printf("the source is %s",source_dir_path);
    //printf("the dest is %s",dest_dir_path);
   
    strcpy(tmpPath, dest_dir_path);
    source_node = search_bstnode(bst_root, source_dir_path);
   
    dest_node = search_bstnode(bst_root, dest_dir_path);
   
    
     if(source_node == -100) {
           printf("%s\n",ERR_VFS_MOVEDIR_01); //ERR_VFS_MOVEDIR_01
            return;
    }
   
    else if(source_node != -100 && source_node >= 0) {
            printf("%s\n",ERR_VFS_MOVEDIR_04);//ERR_VFS_MOVEDIR_04       
            return;
    }
   
    else if(dest_node ==-100) {
        printf("%s\n",ERR_VFS_MOVEDIR_02);
        //printf("CANNOT_FIND_SPECIFIED_DESTINATIONDIR");//ERR_VFS_MOVEDIR_02
        return;
    }
    else if(dest_node != -100 && dest_node >= 0) {
            printf("%s\n",ERR_VFS_MOVEDIR_07);//ERR_VFS_MOVEDIR_07   
            return;
    }
   
    else
    {   
        if(strstr(source_dir_path, dest_dir_path)!=NULL) {
            printf("%s\n",ERR_VFS_MOVEDIR_06);//ERR_VFS_MOVEDIR_06        
            return;
        }
        else if (srcdirInDest(source_dir_path, tmpPath)) {
            printf("%s\n",ERR_VFS_MOVEDIR_05);    //ERR_VFS_MOVEDIR_05
            return;           
        }
        else {
        //printf("\nchecking");   
        srcroot = source_node_remove(source_dir_path);   
        //printf("the dest path path  is %s",dest_dir_path);
        destnode_moved(srcroot, dest_dir_path);
        set_newpath(srcroot,dest_dir_path );
        //printf("\nmovedir done");
        //display_nary(naryroot);
        bst_root=NULL;
        constructBST(naryroot);
        //display_bst(bst_root);
        //display_bst(bst_root);
        printf("movedir_SUCCESS\n");
        }
    }
    return;
}


int srcdirInDest(char src_path[], char path[])
{   
    char *currDirName;
    int c =0;
    int result;
    currDirName = find_dirname(src_path);
    if(strcmp(path,"/")!=0)
    strcat(path,"/");
    strcat(path,currDirName);
    result = search_bstnode(bst_root, path);
    if(result != -100)
        c =1;
    return c;
}

//ADD FILE
/*
#define ERR_VFS_ADDFILE_00 "addfile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_ADDFILE_02 "addfile_FAILURE INVALID_CHARACTER_IN_FILENAME"
#define ERR_VFS_ADDFILE_03 "addfile_FAILURE FILE_ALREADY_EXISTS"
#define ERR_VFS_ADDFILE_04 "addfile_FAILURE FILE_SYSTEM_FULL"
//New
#define ERR_VFS_ADDFILE_05 "addfile_FAILURE CANNOT_WRITE_TO_DATAFILE" 
//New : (if data exceeds block size)
#define ERR_VFS_ADDFILE_06 "addfile_FAILURE FILE_TOO_LARGE"
//New
#define ERR_VFS_ADDFILE_07 "addfile_FAILURE VFS_NOT_MOUNTED"

*/

int add_file(char *dest_dir_path, char *file_name, char *data)  //Here “data” corresponds to an external file residing in the hard disk.
	{
	if(mountState==0){
		printf("%s\n",ERR_VFS_ADDFILE_07);
		return 0; 
   	}
	if (strlen(dest_dir_path) == 0 || strlen(file_name) == 0 || strlen(data) == 0 ) {
		printf("%s\n",ERR_VFS_ADDFILE_00);
		return 0;
	 }
	 
	 int a;
	for(a=0; file_name[a]!='\0'; a++)
		if(file_name[a]=='/'){
		printf("%s\n",ERR_VFS_ADDFILE_02);
		return 0;
		}
		if(main_header1.max_file_descriptor == main_header1.used_file_descriptor){
		printf("%s\n",ERR_VFS_ADDFILE_04);
		return 0;
	 	}
	 
		char buffer[1024];
		int i=0, k, index=0;
                fd *filedescriptor;
                filedescriptor=(fd*)malloc(sizeof(fd));
                
                int blocknum = search_bstnode (bst_root,dest_dir_path);
        	if (blocknum != -100){
        	printf("%s\n",ERR_VFS_ADDFILE_03);
        	return 0;
        	}
        	
        	blocknum = search_bstnode (bst_root,dest_dir_path);
        	if (blocknum == -100){
        	printf("%s\n",ERR_VFS_ADDFILE_05);
        	return 0;
        	}

		//copying the content of the file(fromHarddisk) in binary mode and adding it to a buffer

		FILE *fp = fopen(data, "rb");            //opening the file in rb mode.
		
		
		
		char ch;
		fseek(fp, 0, SEEK_SET);
		while( !feof(fp) )
		{
			fread(&ch, sizeof(char), 1, fp);           //reading the file character by character
			buffer[i++] = ch;             		//storing each ch into buffer
		}
		
		if(i>=1024){
		fclose(fp);
		 printf("%s\n",ERR_VFS_ADDFILE_06);
		 return 0;
		}
		
		buffer[i]='\0';                                 //adding /0 as last element of the file
		fclose(fp);                                     //closing/saving the file
		
		fp = fopen(main_header1.file_system_label, "rb+");
		//code for finding the freeblock and its  location
                k = 0;
                while(*(freelist+k)!=0)  //finding a free block
                   k++;
                
		int free_block_location = block_startpoint + k*sizeof(block);
		//printf("k=%d and free block location = %d\n",k,free_block_location);

		//Adding FD to data structures
                strcpy(filedescriptor->filename, file_name);
                strcat(dest_dir_path, "/");
                strcat(dest_dir_path, file_name);
                strcpy(filedescriptor->path, dest_dir_path);
                strcpy(filedescriptor->filetype, "file");
                filedescriptor->filesize = i+1;
                filedescriptor->blockno = k;
  
                naryroot = insert_nary(filedescriptor);   
                bst_root = insert_bstnode(bst_root, filedescriptor);
                index = hash_val(fd1.filename);
	        array[index] = insertnode(array[index],&fd1);

		//writing buffer into the Block(free) and update the free list
                
		
		//printf("k=%d\n",k);
                *(freelist+k) = 1; //updating the free list
		file_descriptors[fd_count]=filedescriptor;
                fd_count++;
		fseek(fp, free_block_location, SEEK_SET);             //seeking to the freeblock location
		block b;
		strcpy(b.data, buffer);                       //copy the buffer content to the block
		fwrite( &b, sizeof(block), 1,fp);           //writing the block(with data) back

		main_header1.used_blocks++;                   //updating the used_block count on main_header
		main_header1.used_file_descriptor++;	    //updating the usedFD count on main_header
		fclose(fp);
                
        	printf("addfile_SUCCESS\n");        

		return 1;
	}
	
//LIST FILE
/*
#define ERR_VFS_LISTFILE_00 "listfile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_LISTFILE_01 "listfile_FAILURE SOURCE_FILE_PATH_NOT_FOUND"
#define ERR_VFS_LISTFILE_02 "listfile_FAILURE NOT_A_TEXT_FILE"
//New
#define ERR_VFS_LISTFILE_03 "listfile_FAILURE CANNOT_CREATE_OUTPUTFILE"
//New
#define ERR_VFS_LISTFILE_04 "listfile_FAILURE VFS_NOT_MOUNTED"

*/

int list_file(char *filepath, char *outputfile){


	if(mountState==0){
		printf("%s\n",ERR_VFS_LISTFILE_04);
		return 0; 
   	}
	if (strlen(filepath) == 0 || strlen(outputfile)==0) {
		printf("%s\n",ERR_VFS_LISTFILE_00);
		return 0;
	 }
	 
	 FILE *fp10 = fopen(outputfile, "r");       //checking otput file is textfile or not
	if(fp10==NULL){
	printf("%s\n",ERR_VFS_LISTFILE_03);
	return 0;
	}
	fclose(fp10);
	 
	 int dest_node = search_bstnode(bst_root,filepath);
	
	if(dest_node ==-1){
		printf("%s\n",ERR_VFS_LISTFILE_01);
	return 0;
	}

    	char str[2000];
    	long temp;
    	
	FILE *fp,*fphd;
	fp=fopen(main_header1.file_system_label,"rb+");
	char path[30];
	char filename[50];
	int l=strlen(filepath);
                
	int i=l-1;
	int j=0;
	while(i>=0)
	{
	   if(filepath[i]=='.')
	   break;
	   i--;
	}
        i++;
        //printf("\n%d\n", i);
        while(i<l)
        {
	   filename[j]=filepath[i];
	   j++;
	   i++;
        }
        filename[j]='\0';
        //printf("%s\n", filename);
        j=0;
	i--;

	if(strcmp(filename,"txt")!=0)
	printf("%s\n",ERR_VFS_LISTFILE_03);
	return 0;

	fseek(fp, block_startpoint, SEEK_SET);
	temp= search_bstnode (bst_root,filepath);
	fseek(fp,sizeof(block)*temp,SEEK_CUR);
	fread(str, sizeof(block), 1, fp);
	fphd=fopen(outputfile,"w+");
	
	int ch;
	if(fphd==NULL)
	  perror("fopen"); 		
        for(i=0; i<strlen(str); i++){
         ch = str[i];
         fputc(ch, fphd);
        }
        
       
	fclose(fp);
	fclose(fphd);
	printf("listfile_SUCCESS");
	return 1;
	//return "SUCCESS";
	
}

//EXPORT FILE
/*
#define ERR_VFS_EXPORTFILE_00 "exportfile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_EXPORTFILE_01 "exportfile_FAILURE CANNOT_FIND_SOURCEFILE"
#define ERR_VFS_EXPORTFILE_02 "exportfile_FAILURE CANNOT_CREATE_OUTPUTFILE"
#define ERR_VFS_EXPORTFILE_03 "exportfile_FAILURE CANNOT_EXPORT_DIR"
//New
#define ERR_VFS_EXPORTFILE_04 "exportfile_FAILURE VFS_NOT_MOUNTED"
*/
int export_file(char *vfs_file_path,char *hard_disk_path){

	if(mountState==0){
		printf("%s\n",ERR_VFS_EXPORTFILE_04);
		return 0; 
   	}
	if (strlen(vfs_file_path) == 0 || strlen(hard_disk_path)==0) {
		printf("%s\n",ERR_VFS_EXPORTFILE_00);
		return 0;
	 }

	FILE *fp2 = fopen(hard_disk_path, "wb+");
	if(!fp2){
	printf("%s\n",ERR_VFS_EXPORTFILE_02);
	return 0;
	}
	fclose(fp2);

if(vfs_file_path == NULL){
		printf("%s\n",ERR_VFS_EXPORTFILE_00);
		return 0;
	 }
	
char *str;
int temp;
FILE *fp,*fphd;
fp=fopen(main_header1.file_system_label,"rb+");

//fseek(fp,sizeof(Header) + sizeof(fd) * Header.max_file_descriptor + sizeof(block) * Header.Total_Blocks,SEEK_SET);
fseek(fp,block_startpoint,SEEK_SET);
temp= search_bstnode (bst_root,vfs_file_path);
if(temp ==-100){
printf("%s\n",ERR_VFS_EXPORTFILE_01);
return 0;
}

str=malloc(1024*sizeof(char));

fseek(fp,sizeof(block)*temp,SEEK_CUR);
fread(str,sizeof(block),1,fp);

//printf("%s",str);
//printf("\n LEN:%d",strlen(str));

fphd=fopen(hard_disk_path,"wb+");
fwrite(str,sizeof(char),strlen(str),fphd);

fclose(fp);
fclose(fphd);
printf("exportfile_SUCCESS");
return 1;
}

//REMOVE FILE
/*
#define ERR_VFS_REMOVEFILE_00 "removefile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
// Use this error even when the given argument is a directory and not a file
#define ERR_VFS_REMOVEFILE_01 "removefile_FAILURE CANNOT_FIND_SPECIFIED_FILE"
//New
#define ERR_VFS_REMOVEFILE_02 "removefile_FAILURE VFS_NOT_MOUNTED"
*/
int remove_file(char *filepath){

	if(mountState==0){
		printf("%s\n",ERR_VFS_REMOVEFILE_02);
		return 0; 
   	}
	if (strlen(filepath) == 0) {
		printf("%s\n",ERR_VFS_REMOVEFILE_00);
		return 0;
	 }

   int blocknum = search_bstnode (bst_root,filepath);
        
   
   int i;
 
   //printf("\nblockno = %d", blocknum);  // blockno of -1 corresponds to folder and -100 means filepath doesn't exist...so we can proceed only if blockno >=0
   
    if(blocknum < 0){
     printf("%s\n",ERR_VFS_REMOVEFILE_01);
     return 0;
    }

  for(i=0;i<fd_count;i++)
  {
    if(blocknum==file_descriptors[i]->blockno)
   {
    break;
   }
  }
  
  if(i<fd_count)
  {
   delete_nary(file_descriptors[i]);
   delete_bstnode(bst_root, filepath);
   
   int index=hash_val(file_descriptors[i]->filename);
   array[index]=delete_file1(array[index],file_descriptors[i]);
   //delete_file1();
  }
  else
   return 0;
  
  for(; (i+1)<fd_count; i++)
  {
   file_descriptors[i] = file_descriptors[i+1];
  }
  fd_count--;
  *(freelist+blocknum) = 0; 
  main_header1.used_file_descriptor--;
  main_header1.used_blocks--;

printf("removefile_SUCCESS\n");
  return 1;
}
//UPDATE FILE
/*
#define ERR_VFS_UPDATEFILE_00 "updatefile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_UPDATEFILE_01 "updatefile_FAILURE INTERNAL_FILE_NOT_FOUND"
#define ERR_VFS_UPDATEFILE_02 "updatefile_FAILURE EXTERNAL_FILE_NOT_FOUND"
//New
#define ERR_VFS_UPDATEFILE_03 "updatefile_FAILURE EXTERNAL_FILE_TOO_LARGE"
//New
#define ERR_VFS_UPDATEFILE_04 "updatefile_FAILURE VFS_NOT_MOUNTED"
*/

int update_file(char *filepath, char *data){


	if(mountState==0){
		printf("%s\n",ERR_VFS_UPDATEFILE_00);
		return 0; 
   	}
	if (strlen(filepath) == 0 || strlen(data) == 0 ) {
		printf("%s\n",ERR_VFS_UPDATEFILE_04);
		return 0;
	 }

        fd *fd1=NULL;
        FILE *fp=NULL;
        int i,j,flag=0,position;
        char path[30],filename[30];
       // printf("step1\n");
        
        for(i=strlen(filepath)-1;i>0;i--)
        {
       if(filepath[i]=='/')
          break;
        }
  


        int blocknum = search_bstnode (bst_root,filepath);
        if (blocknum== -100){
        printf("%s\n",ERR_VFS_UPDATEFILE_01);
        return 0;
        }
        
        for(i=0;i<fd_count;i++)
     {
          if(blocknum==file_descriptors[i]->blockno)
          {
               break;
          }
     }
     //printf("i=%d\n",i);
     if(i==fd_count){
     //printf("not found\n");
         return 0;
         }
                 fp=fopen(main_header1.file_system_label,"wb+");
            if(fp==NULL){
                //printf("fp=NULL\n");
           }
           long block_pos=block_startpoint+(blocknum*sizeof(block));
            
            FILE *fphd=fopen(data,"rb");
            if(fphd==NULL){
                printf("%s\n",ERR_VFS_UPDATEFILE_02);
                
                return 0;
                }
            fseek(fphd,0,SEEK_END);
            long s=ftell(fphd);
            //printf("%d",s);
            if(s>1024){
            printf("%s\n",ERR_VFS_UPDATEFILE_03);
                return 0;
                }
            fseek(fp,block_pos,SEEK_SET);
            char str[1024];
            rewind(fphd);
            fread(str,s,1,fphd);
            str[s]='\0';
                      
            fwrite(str,sizeof(block),1,fp);
            fclose(fp);
             
            return 1;
        }


//Searchfile
/*
#define ERR_VFS_SEARCHFILE_00 "searchfile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
//New
#define ERR_VFS_SEARCHFILE_02 "searchfile_FAILURE VFS_NOT_MOUNTED"
*/
int search_file1(char *name, char *outputfile)
{

	if(mountState==0){
		printf("%s\n",ERR_VFS_SEARCHFILE_02);
		return 0; 
   	}
	if (strlen(name) == 0 || strlen(outputfile) == 0 ) {
		printf("%s\n",ERR_VFS_SEARCHFILE_00);
		return 0;
	 }

        FILE *fp;
        int count=0;
    Node *temp,*start;
    temp =  fileSearch(name);
    start=temp;
    
        //printf("\nDisplaying hash...\n");
        //display_hash();
    if(temp==NULL){
          //printf("\n222222222\n");
      return 0;
    }
    else
    {
          //printf("\n11111111111111111\n");
          fp=fopen(outputfile,"w");
           if(fp==NULL)
                return 0;
            
            else
         { 
               
               while(start!=NULL)
               {
                 count++;
         fprintf(fp,"File name is %s\t",((struct file_descriptor *)(start->data))->filename);        
                 fprintf(fp,"File path is %s\n",((struct file_descriptor *)(start->data))->path);
        
                 start=start->next;
               }
                fclose(fp);
                return count;
        }
     }
        
}


//COPYFILE
/*
#define ERR_VFS_COPYFILE_00 "copyfile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_COPYFILE_01 "copyfile_FAILURE CANNOT_FIND_SOURCEFILE"
#define ERR_VFS_COPYFILE_02 "copyfile_FAILURE CANNOT_FIND_DESTINATIONFILE"
#define ERR_VFS_COPYFILE_03 "copyfile_FAILURE CANNOT_COPY_DIR_TO_FILE"
#define ERR_VFS_COPYFILE_04 "copyfile_FAILURE FILE_SYSTEM_FULL"
#define ERR_VFS_COPYFILE_05 "copyfile_FAILURE VFS_NOT_MOUNTED"

*/

int copy_file(char *sourcePath,char *destPath){
	
	if(mountState==0){
		printf("%s\n",ERR_VFS_COPYFILE_05);
		return 0; 
   	}
	if (strlen(sourcePath) == 0 || strlen(destPath) == 0 ) {
		printf("%s\n",ERR_VFS_COPYFILE_00);
		return 0;
	 }
	 
	 int temp= search_bstnode (bst_root,sourcePath);
	if(temp ==-100){
	printf("%s\n",ERR_VFS_COPYFILE_01);
	return 0;
	}
	 int dest_node = search_bstnode(bst_root,destPath);
		if(dest_node ==-100){
		printf("%s\n",ERR_VFS_COPYFILE_02);
		return 0;
	}
	
	if(main_header1.max_file_descriptor == main_header1.used_file_descriptor){
		printf("%s\n",ERR_VFS_COPYFILE_04);
		return 0;
	
	
	}
	
	
//printf(copyfile to be done);
	char buffer[1024];
       int blockno_source = search_bstnode(bst_root, sourcePath);

       if(blockno_source==-100)
         return 0; //cannot find source file

       int blockno_dest = search_bstnode(bst_root, destPath);
      
       if(blockno_dest==-100)
        return 0; //cannot find destination file

       FILE *fp = fopen(main_header1.file_system_label, "rb+");
              
       fseek(fp, block_startpoint, SEEK_SET);
       fseek(fp,sizeof(block)*blockno_source,SEEK_CUR);
       int i=0;
       fread(&buffer[i], sizeof(char), 1, fp);
       
       while(buffer[i]!='\0'){
        fread(&buffer[++i], sizeof(char), 1, fp);
       }
      
       fseek(fp, block_startpoint, SEEK_SET);
       fseek(fp, sizeof(block)*blockno_dest, SEEK_CUR);
       fwrite(buffer, sizeof(block), 1, fp);
       fclose(fp);




printf("copyfile_SUCCESS\n");
return 0;
}



//MOVEFILE
/*
#define ERR_VFS_MOVEFILE_00 "movefile_FAILURE VFS_INSUFFICIENT_ARGUMENTS"
#define ERR_VFS_MOVEFILE_01 "movefile_FAILURE CANNOT_FIND_SOURCEFILE"
#define ERR_VFS_MOVEFILE_02 "movefile_FAILURE CANNOT_FIND_DESTINATION_PATH"
#define ERR_VFS_MOVEFILE_05 "movefile_FAILURE DESTINATION_CANNOT_BE_FILE"
//New
#define ERR_VFS_MOVEFILE_06 "movefile_FAILURE VFS_NOT_MOUNTED"

*/
int move_file(char *sourcePath,char *destPath){
	
	
	if(mountState==0){
		printf("%s\n",ERR_VFS_MOVEFILE_06);
		return 0; 
   	}
	if (strlen(sourcePath) == 0 || strlen(destPath) == 0 ) {
		printf("%s\n",ERR_VFS_MOVEFILE_00);
		return 0;
	 }
	
	int temp= search_bstnode (bst_root,sourcePath);
	if(temp ==-100){
	printf("%s\n",ERR_VFS_MOVEFILE_01);
	return 0;
	}

	int dest_node = search_bstnode(bst_root,destPath);
		if(dest_node ==-1) {
		printf("%s\n",ERR_VFS_MOVEFILE_02);
		return 0;
	}
	if(dest_node != -100 && dest_node >= 0) {
			printf("%s\n",ERR_VFS_MOVEFILE_05);	
			return;
	}
	
	
	//moveFile;
	
	
	char buffer[1024];
       int blockno_source = search_bstnode(bst_root, sourcePath);

       

       int blockno_dest = search_bstnode(bst_root, destPath);
      
       
    //printf("%d HIIIIIIIII M BLOCK NUM \n",blockno_dest); 
    if(blockno_dest>=0){
      
             FILE *fp = fopen(main_header1.file_system_label, "rb+");     
               fseek(fp, block_startpoint, SEEK_SET);
               fseek(fp,sizeof(block)*blockno_source,SEEK_CUR);
               int i=0;
               fread(&buffer[i], sizeof(char), 1, fp);
       
               while(buffer[i]!='\0'){
                fread(&buffer[++i], sizeof(char), 1, fp);
               }
       
               //printf("\nbuffer = %s\n", buffer);
               fseek(fp, block_startpoint, SEEK_SET);
               fseek(fp, sizeof(block)*blockno_dest, SEEK_CUR);
               fwrite(buffer, sizeof(block), 1, fp);
               char str[1024];
               fseek(fp, block_startpoint, SEEK_SET);
               fseek(fp, sizeof(block)*blockno_dest, SEEK_CUR);
               fread(str, sizeof(block), 1, fp);
               //printf("\nstr = %s\n", str);
               remove_file(sourcePath);
               fclose(fp);
        }
    else{
    
            char* path1 = "/tmp/movedata";
         char* filename;
         char filepath[150];
         int i;
         list_file(sourcePath, path1);
    
         char *temp = strtok(sourcePath, "/"); 
         while(temp!=NULL){ 
          filename = temp; 
          temp = strtok(NULL, "/"); 
         }           
    for(i=strlen(destPath)-1;i>0;i--)
      {
          if(destPath[i]=='/')
              break;
      }

        int position = i;
        for(i=0; i<position; i++)
          filepath[i] = destPath[i];
        filepath[i] = '\0';
      
        add_file(filepath, filename, path1);
        remove_file(sourcePath);
    


    }
	
	
	
	
	
	printf("movefile_SUCCESS\n");
	return 0;
}
